revanced-integrations/app/src/main/java/app/revanced/integrations/sponsorblock/SponsorBlockUtils.java

657 lines
31 KiB
Java
Raw Normal View History

2022-06-24 00:16:32 +02:00
package app.revanced.integrations.sponsorblock;
2020-08-24 17:47:57 +02:00
2021-07-30 19:30:00 +02:00
import static android.text.Html.fromHtml;
import static android.view.View.GONE;
import static android.view.View.VISIBLE;
2022-06-24 00:16:32 +02:00
import static app.revanced.integrations.sponsorblock.PlayerController.getCurrentVideoId;
import static app.revanced.integrations.sponsorblock.PlayerController.getCurrentVideoLength;
import static app.revanced.integrations.sponsorblock.PlayerController.getLastKnownVideoTime;
import static app.revanced.integrations.sponsorblock.PlayerController.sponsorSegmentsOfCurrentVideo;
import static app.revanced.integrations.settingsmenu.SponsorBlockSettingsFragment.FORMATTER;
import static app.revanced.integrations.settingsmenu.SponsorBlockSettingsFragment.SAVED_TEMPLATE;
2022-06-24 00:16:32 +02:00
import static app.revanced.integrations.sponsorblock.StringRef.str;
import static app.revanced.integrations.sponsorblock.requests.SBRequester.voteForSegment;
2021-07-30 19:30:00 +02:00
2020-08-24 17:47:57 +02:00
import android.annotation.SuppressLint;
import android.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface;
2021-07-23 14:56:54 +02:00
import android.content.Intent;
2021-07-27 19:58:14 +02:00
import android.content.SharedPreferences;
2021-07-23 14:56:54 +02:00
import android.net.Uri;
import android.preference.EditTextPreference;
import android.preference.Preference;
import android.preference.PreferenceCategory;
2021-04-22 18:43:14 +02:00
import android.text.Html;
2021-07-23 23:24:51 +02:00
import android.text.TextUtils;
2022-06-24 00:16:32 +02:00
2020-08-24 17:47:57 +02:00
import android.view.View;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.Toast;
import org.json.JSONArray;
import org.json.JSONObject;
2020-08-24 17:47:57 +02:00
import java.lang.ref.WeakReference;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
2021-06-18 14:46:55 +02:00
import java.util.List;
2020-08-24 17:47:57 +02:00
import java.util.Objects;
import java.util.TimeZone;
import app.revanced.integrations.settings.SettingsEnum;
2022-06-24 00:16:32 +02:00
import app.revanced.integrations.sponsorblock.player.PlayerType;
import app.revanced.integrations.utils.LogHelper;
import app.revanced.integrations.utils.ReVancedUtils;
2022-06-24 00:16:32 +02:00
import app.revanced.integrations.utils.SharedPrefHelper;
import app.revanced.integrations.sponsorblock.objects.SponsorSegment;
import app.revanced.integrations.sponsorblock.objects.UserStats;
import app.revanced.integrations.sponsorblock.requests.SBRequester;
2021-07-19 16:19:47 +02:00
2020-08-24 17:47:57 +02:00
public abstract class SponsorBlockUtils {
public static final String DATE_FORMAT = "HH:mm:ss.SSS";
@SuppressLint("SimpleDateFormat")
public static final SimpleDateFormat dateFormatter = new SimpleDateFormat(DATE_FORMAT);
2021-07-23 23:50:57 +02:00
public static boolean videoHasSegments = false;
public static String timeWithoutSegments = "";
2020-08-24 17:47:57 +02:00
private static final int sponsorBtnId = 1234;
2022-02-07 16:15:22 +01:00
private static final String LOCKED_COLOR = "#FFC83D";
2021-07-19 16:19:47 +02:00
public static final View.OnClickListener sponsorBlockBtnListener = v -> {
LogHelper.printDebug(() -> "Shield button clicked");
2021-07-19 16:19:47 +02:00
NewSegmentHelperLayout.toggle();
2020-08-24 17:47:57 +02:00
};
2021-07-19 16:19:47 +02:00
public static final View.OnClickListener voteButtonListener = v -> {
LogHelper.printDebug(() -> "Vote button clicked");
2021-07-19 16:19:47 +02:00
SponsorBlockUtils.onVotingClicked(v.getContext());
2021-04-22 18:43:14 +02:00
};
2020-08-24 17:47:57 +02:00
private static int shareBtnId = -1;
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();
2020-08-24 17:47:57 +02:00
break;
case DialogInterface.BUTTON_POSITIVE:
// end
newSponsorSegmentEndMillis = newSponsorSegmentDialogShownMillis;
Toast.makeText(context.getApplicationContext(), str("new_segment_time_end_set"), Toast.LENGTH_SHORT).show();
2020-08-24 17:47:57 +02:00
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) {
2021-06-18 14:46:55 +02:00
SponsorBlockSettings.SegmentInfo segmentType = SponsorBlockSettings.SegmentInfo.valuesWithoutUnsubmitted()[which];
2020-08-24 17:47:57 +02:00
boolean enableButton;
if (!segmentType.behaviour.showOnTimeBar) {
Toast.makeText(
((AlertDialog) dialog).getContext().getApplicationContext(),
str("new_segment_disabled_category"),
2020-08-24 17:47:57 +02:00
Toast.LENGTH_SHORT).show();
enableButton = false;
} else {
Toast.makeText(
((AlertDialog) dialog).getContext().getApplicationContext(),
segmentType.description.toString(),
2020-08-24 17:47:57 +02:00
Toast.LENGTH_SHORT).show();
newSponsorBlockSegmentType = segmentType;
enableButton = true;
}
((AlertDialog) dialog)
.getButton(DialogInterface.BUTTON_POSITIVE)
.setEnabled(enableButton);
}
};
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();
2021-06-18 14:46:55 +02:00
SponsorBlockSettings.SegmentInfo[] values = SponsorBlockSettings.SegmentInfo.valuesWithoutUnsubmitted();
2020-08-24 17:47:57 +02:00
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"))
2020-08-24 17:47:57 +02:00
.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 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();
2020-08-24 17:47:57 +02:00
appContext = new WeakReference<>(context);
ReVancedUtils.runOnBackgroundThread(submitRunnable);
2020-08-24 17:47:57 +02:00
}
};
2021-07-19 16:19:47 +02:00
public static String messageToToast = "";
private static final EditByHandSaveDialogListener editByHandSaveDialogListener = new EditByHandSaveDialogListener();
private static final DialogInterface.OnClickListener editByHandDialogListener = (dialog, which) -> {
Context context = ((AlertDialog) dialog).getContext();
final boolean isStart = DialogInterface.BUTTON_NEGATIVE == which;
final EditText textView = new EditText(context);
textView.setHint(DATE_FORMAT);
if (isStart) {
if (newSponsorSegmentStartMillis >= 0)
textView.setText(dateFormatter.format(new Date(newSponsorSegmentStartMillis)));
} else {
if (newSponsorSegmentEndMillis >= 0)
textView.setText(dateFormatter.format(new Date(newSponsorSegmentEndMillis)));
}
2020-08-24 17:47:57 +02:00
2021-07-19 16:19:47 +02:00
editByHandSaveDialogListener.settingStart = isStart;
editByHandSaveDialogListener.editText = new WeakReference<>(textView);
new AlertDialog.Builder(context)
.setTitle(str(isStart ? "new_segment_time_start" : "new_segment_time_end"))
.setView(textView)
.setNegativeButton(android.R.string.cancel, null)
.setNeutralButton(str("new_segment_now"), editByHandSaveDialogListener)
.setPositiveButton(android.R.string.ok, editByHandSaveDialogListener)
.show();
2020-08-24 17:47:57 +02:00
2021-07-19 16:19:47 +02:00
dialog.dismiss();
2020-08-24 17:47:57 +02:00
};
2021-07-19 16:19:47 +02:00
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];
2021-04-22 20:19:00 +02:00
2021-07-19 16:19:47 +02:00
final VoteOption[] voteOptions = VoteOption.values();
2022-02-07 16:15:22 +01:00
CharSequence[] items = new CharSequence[voteOptions.length];
2021-04-22 20:19:00 +02:00
2021-07-19 16:19:47 +02:00
for (int i = 0; i < voteOptions.length; i++) {
2022-02-07 16:15:22 +01:00
VoteOption voteOption = voteOptions[i];
String title = voteOption.title;
if (SettingsEnum.SB_IS_VIP.getBoolean() && segment.isLocked && voteOption.shouldHighlight) {
2022-02-07 16:15:22 +01:00
items[i] = Html.fromHtml(String.format("<font color=\"%s\">%s</font>", LOCKED_COLOR, title));
2022-06-24 00:16:32 +02:00
} else {
2022-02-07 16:15:22 +01:00
items[i] = title;
}
2021-04-22 18:43:14 +02:00
}
2020-08-24 17:47:57 +02:00
2021-07-19 16:19:47 +02:00
new AlertDialog.Builder(context)
.setItems(items, (dialog1, which1) -> {
appContext = new WeakReference<>(context.getApplicationContext());
2022-01-25 22:52:11 +01:00
VoteOption voteOption = voteOptions[which1];
switch (voteOption) {
2021-07-19 16:19:47 +02:00
case UPVOTE:
case DOWNVOTE:
2022-01-25 22:52:11 +01:00
voteForSegment(segment, voteOption, appContext.get());
2021-07-19 16:19:47 +02:00
break;
case CATEGORY_CHANGE:
onNewCategorySelect(segment, context);
break;
}
})
.show();
};
private static final Runnable submitRunnable = () -> {
messageToToast = null;
final String uuid = SettingsEnum.SB_UUID.getString();
2021-07-19 16:19:47 +02:00
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) {
LogHelper.printException(() -> "Unable to submit times, invalid parameters");
2021-07-19 16:19:47 +02:00
return;
2020-08-24 17:47:57 +02:00
}
2022-01-17 14:54:11 +01:00
SBRequester.submitSegments(videoId, uuid, ((float) start) / 1000f, ((float) end) / 1000f, segmentType.key, toastRunnable);
2021-07-19 16:19:47 +02:00
newSponsorSegmentEndMillis = newSponsorSegmentStartMillis = -1;
} catch (Exception e) {
LogHelper.printException(() -> "Unable to submit segment", e);
2020-08-24 17:47:57 +02:00
}
2021-07-19 16:19:47 +02:00
if (videoId != null)
PlayerController.executeDownloadSegments(videoId);
2020-08-24 17:47:57 +02:00
};
static {
dateFormatter.setTimeZone(TimeZone.getTimeZone("UTC"));
}
private SponsorBlockUtils() {
}
2021-04-22 18:43:14 +02:00
public static void showShieldButton() {
View i = ShieldButton._shieldBtn.get();
2021-04-29 23:05:23 +02:00
if (i == null || !ShieldButton.shouldBeShown()) return;
2020-08-24 17:47:57 +02:00
i.setVisibility(VISIBLE);
i.bringToFront();
i.requestLayout();
i.invalidate();
}
2021-04-22 18:43:14 +02:00
public static void hideShieldButton() {
View i = ShieldButton._shieldBtn.get();
2020-08-24 17:47:57 +02:00
if (i != null)
i.setVisibility(GONE);
}
2021-04-22 18:43:14 +02:00
public static void showVoteButton() {
View i = VotingButton._votingButton.get();
2021-04-29 23:05:23 +02:00
if (i == null || !VotingButton.shouldBeShown()) return;
2021-04-22 18:43:14 +02:00
i.setVisibility(VISIBLE);
i.bringToFront();
i.requestLayout();
i.invalidate();
}
public static void hideVoteButton() {
View i = VotingButton._votingButton.get();
2021-04-22 18:43:14 +02:00
if (i != null)
i.setVisibility(GONE);
}
2020-08-24 17:47:57 +02:00
@SuppressLint("DefaultLocale")
public static void onMarkLocationClicked(Context context) {
newSponsorSegmentDialogShownMillis = PlayerController.getLastKnownVideoTime();
new AlertDialog.Builder(context)
.setTitle(str("new_segment_title"))
2021-07-19 21:51:26 +02:00
.setMessage(str("new_segment_mark_time_as_question",
2020-08-24 17:47:57 +02:00
newSponsorSegmentDialogShownMillis / 60000,
newSponsorSegmentDialogShownMillis / 1000 % 60,
newSponsorSegmentDialogShownMillis % 1000))
.setNeutralButton(android.R.string.cancel, null)
.setNegativeButton(str("new_segment_mark_start"), newSponsorSegmentDialogListener)
.setPositiveButton(str("new_segment_mark_end"), newSponsorSegmentDialogListener)
2020-08-24 17:47:57 +02:00
.show();
}
@SuppressLint("DefaultLocale")
public static void onPublishClicked(Context context) {
if (newSponsorSegmentStartMillis >= 0 && newSponsorSegmentStartMillis < newSponsorSegmentEndMillis) {
long length = (newSponsorSegmentEndMillis - newSponsorSegmentStartMillis) / 1000;
long start = (newSponsorSegmentStartMillis) / 1000;
long end = (newSponsorSegmentEndMillis) / 1000;
new AlertDialog.Builder(context)
.setTitle(str("new_segment_confirm_title"))
2021-07-19 21:51:26 +02:00
.setMessage(str("new_segment_confirm_content",
2020-08-24 17:47:57 +02:00
start / 60, start % 60,
end / 60, end % 60,
length / 60, length % 60))
.setNegativeButton(android.R.string.no, null)
.setPositiveButton(android.R.string.yes, segmentReadyDialogButtonListener)
.show();
} else {
2021-04-22 21:13:39 +02:00
Toast.makeText(context, str("new_segment_mark_locations_first"), Toast.LENGTH_SHORT).show();
2020-08-24 17:47:57 +02:00
}
}
2021-04-22 18:43:14 +02:00
public static void onVotingClicked(final Context context) {
if (sponsorSegmentsOfCurrentVideo == null || sponsorSegmentsOfCurrentVideo.length == 0) {
Toast.makeText(context.getApplicationContext(), str("vote_no_segments"), Toast.LENGTH_SHORT).show();
2021-04-22 18:43:14 +02:00
return;
}
2021-04-25 16:32:35 +02:00
int segmentAmount = sponsorSegmentsOfCurrentVideo.length;
2021-06-18 14:46:55 +02:00
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
2021-04-25 16:32:35 +02:00
for (int i = 0; i < segmentAmount; i++) {
2021-04-22 18:43:14 +02:00
SponsorSegment segment = sponsorSegmentsOfCurrentVideo[i];
2021-07-19 17:32:06 +02:00
if (segment.category == SponsorBlockSettings.SegmentInfo.UNSUBMITTED) {
2021-06-18 14:46:55 +02:00
continue;
}
2021-04-22 18:43:14 +02:00
String start = dateFormatter.format(new Date(segment.start));
String end = dateFormatter.format(new Date(segment.end));
2021-04-25 16:32:35 +02:00
StringBuilder htmlBuilder = new StringBuilder();
htmlBuilder.append(String.format("<b><font color=\"#%06X\">⬤</font> %s<br> %s to %s",
2021-04-22 18:43:14 +02:00
segment.category.color, segment.category.title, start, end));
2021-04-25 16:32:35 +02:00
if (i + 1 != segmentAmount) // prevents trailing new line after last segment
htmlBuilder.append("<br>");
2021-06-18 14:46:55 +02:00
titles.add(Html.fromHtml(htmlBuilder.toString()));
2021-04-22 18:43:14 +02:00
}
new AlertDialog.Builder(context)
2021-06-18 14:46:55 +02:00
.setItems(titles.toArray(new CharSequence[0]), segmentVoteClickListener)
2021-04-22 18:43:14 +02:00
.show();
}
private static void onNewCategorySelect(final SponsorSegment segment, Context context) {
2021-06-18 14:46:55 +02:00
final SponsorBlockSettings.SegmentInfo[] values = SponsorBlockSettings.SegmentInfo.valuesWithoutUnsubmitted();
2021-04-22 18:43:14 +02:00
CharSequence[] titles = new CharSequence[values.length];
for (int i = 0; i < values.length; i++) {
titles[i] = values[i].getTitleWithDot();
}
new AlertDialog.Builder(context)
.setTitle(str("new_segment_choose_category"))
2022-01-24 13:45:07 +01:00
.setItems(titles, (dialog, which) -> voteForSegment(segment, VoteOption.CATEGORY_CHANGE, appContext.get(), values[which].key))
2021-04-22 18:43:14 +02:00
.show();
}
2020-08-24 17:47:57 +02:00
@SuppressLint("DefaultLocale")
public static void onPreviewClicked(Context context) {
if (newSponsorSegmentStartMillis >= 0 && newSponsorSegmentStartMillis < newSponsorSegmentEndMillis) {
// Toast t = Toast.makeText(context, "Preview", Toast.LENGTH_SHORT);
// t.setGravity(Gravity.CENTER_HORIZONTAL | Gravity.TOP, t.getXOffset(), t.getYOffset());
// t.show();
2020-08-24 17:47:57 +02:00
PlayerController.skipToMillisecond(newSponsorSegmentStartMillis - 3000);
final SponsorSegment[] original = PlayerController.sponsorSegmentsOfCurrentVideo;
final SponsorSegment[] segments = original == null ? new SponsorSegment[1] : Arrays.copyOf(original, original.length + 1);
segments[segments.length - 1] = new SponsorSegment(newSponsorSegmentStartMillis, newSponsorSegmentEndMillis,
2022-02-07 16:15:22 +01:00
SponsorBlockSettings.SegmentInfo.UNSUBMITTED, null, false);
2020-08-24 17:47:57 +02:00
Arrays.sort(segments);
sponsorSegmentsOfCurrentVideo = segments;
} else {
Toast.makeText(context, str("new_segment_mark_locations_first"), Toast.LENGTH_SHORT).show();
2020-08-24 17:47:57 +02:00
}
}
@SuppressLint("DefaultLocale")
public static void onEditByHandClicked(Context context) {
new AlertDialog.Builder(context)
.setTitle(str("new_segment_edit_by_hand_title"))
.setMessage(str("new_segment_edit_by_hand_content"))
2020-08-24 17:47:57 +02:00
.setNeutralButton(android.R.string.cancel, null)
.setNegativeButton(str("new_segment_mark_start"), editByHandDialogListener)
.setPositiveButton(str("new_segment_mark_end"), editByHandDialogListener)
2020-08-24 17:47:57 +02:00
.show();
}
public static void notifyShareBtnVisibilityChanged(View v) {
2022-06-24 00:16:32 +02:00
if (v.getId() != shareBtnId || !/*SponsorBlockSettings.isAddNewSegmentEnabled*/false)
return;
2020-08-24 17:47:57 +02:00
// if (VERBOSE)
2022-06-24 00:16:32 +02:00
// LogH(TAG, "VISIBILITY CHANGED of view " + v);
ImageView sponsorBtn = ShieldButton._shieldBtn.get();
2020-08-24 17:47:57 +02:00
if (sponsorBtn != null) {
sponsorBtn.setVisibility(v.getVisibility());
}
}
2021-07-23 23:50:57 +02:00
public static String appendTimeWithoutSegments(String totalTime) {
try {
if (videoHasSegments && (SettingsEnum.SB_ENABLED.getBoolean() && SettingsEnum.SB_SHOW_TIME_WITHOUT_SEGMENTS.getBoolean()) && !TextUtils.isEmpty(totalTime) && getCurrentVideoLength() > 1) {
if (timeWithoutSegments.isEmpty()) {
timeWithoutSegments = getTimeWithoutSegments(sponsorSegmentsOfCurrentVideo);
}
return totalTime + timeWithoutSegments;
2021-07-26 00:13:33 +02:00
}
} catch (Exception ex) {
LogHelper.printException(() -> "appendTimeWithoutSegments failure", ex);
2021-07-23 23:50:57 +02:00
}
return totalTime;
}
2021-07-26 00:13:33 +02:00
public static String getTimeWithoutSegments(SponsorSegment[] sponsorSegmentsOfCurrentVideo) {
2021-07-28 13:31:27 +02:00
long currentVideoLength = getCurrentVideoLength();
if (!(SettingsEnum.SB_ENABLED.getBoolean() && SettingsEnum.SB_SHOW_TIME_WITHOUT_SEGMENTS.getBoolean()) || sponsorSegmentsOfCurrentVideo == null || currentVideoLength <= 1) {
2021-07-23 23:50:57 +02:00
return "";
}
2021-07-26 00:13:33 +02:00
long timeWithoutSegments = currentVideoLength + 500; // YouTube:tm:
2021-07-23 23:50:57 +02:00
for (SponsorSegment segment : sponsorSegmentsOfCurrentVideo) {
timeWithoutSegments -= segment.end - segment.start;
}
2021-07-24 20:14:47 +02:00
long hours = timeWithoutSegments / 3600000;
long minutes = (timeWithoutSegments / 60000) % 60;
long seconds = (timeWithoutSegments / 1000) % 60;
String format = (hours > 0 ? "%d:%02" : "%") + "d:%02d"; // mmLul
String formatted = hours > 0 ? String.format(format, hours, minutes, seconds) : String.format(format, minutes, seconds);
return String.format(" (%s)", formatted);
2021-07-23 23:50:57 +02:00
}
2022-06-24 00:16:32 +02:00
public static void playerTypeChanged(PlayerType playerType) {
2021-07-23 23:50:57 +02:00
try {
2022-06-24 00:16:32 +02:00
if (videoHasSegments && (playerType == PlayerType.NONE)) {
2021-07-23 23:50:57 +02:00
PlayerController.setCurrentVideoId(null);
}
2022-06-24 00:16:32 +02:00
} catch (Exception ex) {
LogHelper.printException(() -> "Player type changed caused a crash.", ex);
2021-07-23 23:50:57 +02:00
}
}
2021-07-27 17:26:59 +02:00
public static String formatColorString(int color) {
return String.format("#%06X", color);
}
2021-07-23 14:56:54 +02:00
@SuppressWarnings("deprecation")
public static void addUserStats(PreferenceCategory category, Preference loadingPreference, UserStats stats) {
category.removePreference(loadingPreference);
Context context = category.getContext();
2021-07-30 19:30:00 +02:00
String minutesStr = str("minutes");
2021-07-23 14:56:54 +02:00
{
EditTextPreference preference = new EditTextPreference(context);
category.addPreference(preference);
String userName = stats.getUserName();
preference.setTitle(fromHtml(str("stats_username", userName)));
preference.setSummary(str("stats_username_change"));
preference.setText(userName);
preference.setOnPreferenceChangeListener((preference1, newUsername) -> {
appContext = new WeakReference<>(context.getApplicationContext());
2022-01-24 13:45:07 +01:00
SBRequester.setUsername((String) newUsername, preference, toastRunnable);
2021-07-23 14:56:54 +02:00
return false;
});
}
{
Preference preference = new Preference(context);
category.addPreference(preference);
String formatted = FORMATTER.format(stats.getSegmentCount());
preference.setTitle(fromHtml(str("stats_submissions", formatted)));
preference.setSelectable(false);
2021-07-23 14:56:54 +02:00
}
{
Preference preference = new Preference(context);
category.addPreference(preference);
String formatted = FORMATTER.format(stats.getViewCount());
double saved = stats.getMinutesSaved();
int hoursSaved = (int) (saved / 60);
double minutesSaved = saved % 60;
2021-07-30 19:30:00 +02:00
String formattedSaved = String.format(SAVED_TEMPLATE, hoursSaved, minutesSaved, minutesStr);
2021-07-23 14:56:54 +02:00
preference.setTitle(fromHtml(str("stats_saved", formatted)));
preference.setSummary(fromHtml(str("stats_saved_sum", formattedSaved)));
preference.setOnPreferenceClickListener(preference1 -> {
Intent i = new Intent(Intent.ACTION_VIEW);
i.setData(Uri.parse("https://sponsor.ajay.app/stats/"));
preference1.getContext().startActivity(i);
return false;
});
}
{
Preference preference = new Preference(context);
category.addPreference(preference);
String formatted = FORMATTER.format(SettingsEnum.SB_SKIPPED_SEGMENTS.getInt());
2021-07-23 14:56:54 +02:00
long hoursSaved = SettingsEnum.SB_SKIPPED_SEGMENTS_TIME.getLong() / 3600000;
double minutesSaved = (SettingsEnum.SB_SKIPPED_SEGMENTS_TIME.getLong() / 60000d) % 60;
2021-07-30 19:30:00 +02:00
String formattedSaved = String.format(SAVED_TEMPLATE, hoursSaved, minutesSaved, minutesStr);
2021-07-23 14:56:54 +02:00
preference.setTitle(fromHtml(str("stats_self_saved", formatted)));
preference.setSummary(fromHtml(str("stats_self_saved_sum", formattedSaved)));
preference.setSelectable(false);
2021-07-23 14:56:54 +02:00
}
}
public static void importSettings(String json, Context context) {
try {
JSONObject settingsJson = new JSONObject(json);
JSONObject barTypesObject = settingsJson.getJSONObject("barTypes");
JSONArray categorySelectionsArray = settingsJson.getJSONArray("categorySelections");
2022-06-24 00:16:32 +02:00
SharedPreferences.Editor editor = SharedPrefHelper.getPreferences(SharedPrefHelper.SharedPrefNames.SPONSOR_BLOCK).edit();
SponsorBlockSettings.SegmentInfo[] categories = SponsorBlockSettings.SegmentInfo.valuesWithoutUnsubmitted();
for (SponsorBlockSettings.SegmentInfo category : categories) {
String categoryKey = category.key;
JSONObject categoryObject = barTypesObject.getJSONObject(categoryKey);
String color = categoryObject.getString("color");
editor.putString(categoryKey + SponsorBlockSettings.CATEGORY_COLOR_SUFFIX, color);
editor.putString(categoryKey, SponsorBlockSettings.SegmentBehaviour.IGNORE.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);
2021-08-27 17:59:32 +02:00
if (category == null) {
continue;
}
int desktopKey = categorySelectionObject.getInt("option");
SponsorBlockSettings.SegmentBehaviour behaviour = SponsorBlockSettings.SegmentBehaviour.byDesktopKey(desktopKey);
editor.putString(category.key, behaviour.key);
}
SettingsEnum.SB_UUID.saveValue(settingsJson.getString("userID"));
SettingsEnum.SB_IS_VIP.saveValue(settingsJson.getBoolean("isVip"));
SettingsEnum.SB_API_URL.saveValue(settingsJson.getString("serverAddress"));
SettingsEnum.SB_SHOW_TOAST_WHEN_SKIP.saveValue(!settingsJson.getBoolean("dontShowNotice"));
SettingsEnum.SB_SHOW_TIME_WITHOUT_SEGMENTS.saveValue(settingsJson.getBoolean("showTimeWithSkips"));
SettingsEnum.SB_MIN_DURATION.saveValue(Float.valueOf(settingsJson.getString("minDuration")));
SettingsEnum.SB_COUNT_SKIPS.saveValue(settingsJson.getBoolean("trackViewCount"));
Toast.makeText(context, str("settings_import_successful"), Toast.LENGTH_SHORT).show();
2022-06-24 00:16:32 +02:00
} catch (Exception ex) {
LogHelper.printInfo(() -> "failed to import settings", ex); // use info level, as we are showing our own toast
Toast.makeText(context, str("settings_import_failed"), Toast.LENGTH_SHORT).show();
}
}
2021-08-03 16:38:38 +02:00
public static String exportSettings(Context context) {
try {
JSONObject json = new JSONObject();
JSONObject barTypesObject = new JSONObject(); // categories' colors
JSONArray categorySelectionsArray = new JSONArray(); // categories' behavior
SponsorBlockSettings.SegmentInfo[] categories = SponsorBlockSettings.SegmentInfo.valuesWithoutUnsubmitted();
for (SponsorBlockSettings.SegmentInfo category : categories) {
JSONObject categoryObject = new JSONObject();
String categoryKey = category.key;
categoryObject.put("color", formatColorString(category.color));
barTypesObject.put(categoryKey, categoryObject);
int desktopKey = category.behaviour.desktopKey;
if (desktopKey != -1) {
JSONObject behaviorObject = new JSONObject();
behaviorObject.put("name", categoryKey);
behaviorObject.put("option", desktopKey);
categorySelectionsArray.put(behaviorObject);
}
}
json.put("userID", SettingsEnum.SB_UUID.getString());
json.put("isVip", SettingsEnum.SB_IS_VIP.getBoolean());
json.put("serverAddress", SettingsEnum.SB_API_URL.getString());
json.put("dontShowNotice", !SettingsEnum.SB_SHOW_TOAST_WHEN_SKIP.getBoolean());
json.put("showTimeWithSkips", SettingsEnum.SB_SHOW_TIME_WITHOUT_SEGMENTS.getBoolean());
json.put("minDuration", SettingsEnum.SB_MIN_DURATION.getFloat());
json.put("trackViewCount", SettingsEnum.SB_COUNT_SKIPS.getBoolean());
json.put("categorySelections", categorySelectionsArray);
json.put("barTypes", barTypesObject);
2022-02-07 16:29:42 +01:00
return json.toString();
2022-06-24 00:16:32 +02:00
} catch (Exception ex) {
LogHelper.printInfo(() -> "failed to export settings", ex); // use info level, as we are showing our own toast
2021-08-03 16:38:38 +02:00
Toast.makeText(context, str("settings_export_failed"), Toast.LENGTH_SHORT).show();
return "";
}
}
2022-01-27 23:05:46 +01:00
public static boolean isSBButtonEnabled(Context context, String key) {
return SettingsEnum.SB_ENABLED.getBoolean() && SharedPrefHelper.getBoolean(SharedPrefHelper.SharedPrefNames.SPONSOR_BLOCK, key, false);
2022-01-27 23:05:46 +01:00
}
2021-07-19 16:19:47 +02:00
public enum VoteOption {
2022-02-07 16:15:22 +01:00
UPVOTE(str("vote_upvote"), false),
DOWNVOTE(str("vote_downvote"), true),
CATEGORY_CHANGE(str("vote_category"), true);
2021-04-22 20:19:00 +02:00
public final String title;
2022-02-07 16:15:22 +01:00
public final boolean shouldHighlight;
2021-04-22 20:19:00 +02:00
2022-02-07 16:15:22 +01:00
VoteOption(String title, boolean shouldHighlight) {
2021-04-22 20:19:00 +02:00
this.title = title;
2022-02-07 16:15:22 +01:00
this.shouldHighlight = shouldHighlight;
2021-04-22 20:19:00 +02:00
}
}
2020-08-24 17:47:57 +02:00
private static class EditByHandSaveDialogListener implements DialogInterface.OnClickListener {
public boolean settingStart;
public WeakReference<EditText> editText;
@SuppressLint("DefaultLocale")
@Override
public void onClick(DialogInterface dialog, int which) {
final EditText editText = this.editText.get();
if (editText == null) return;
Context context = ((AlertDialog) dialog).getContext();
try {
long time = (which == DialogInterface.BUTTON_NEUTRAL) ?
getLastKnownVideoTime() :
(Objects.requireNonNull(dateFormatter.parse(editText.getText().toString())).getTime());
if (settingStart)
newSponsorSegmentStartMillis = Math.max(time, 0);
else
newSponsorSegmentEndMillis = time;
if (which == DialogInterface.BUTTON_NEUTRAL)
editByHandDialogListener.onClick(dialog, settingStart ?
DialogInterface.BUTTON_NEGATIVE :
DialogInterface.BUTTON_POSITIVE);
else
Toast.makeText(context.getApplicationContext(), str("new_segment_edit_by_hand_saved"), Toast.LENGTH_SHORT).show();
2020-08-24 17:47:57 +02:00
} catch (ParseException e) {
Toast.makeText(context.getApplicationContext(), str("new_segment_edit_by_hand_parse_error"), Toast.LENGTH_LONG).show();
2020-08-24 17:47:57 +02:00
}
}
}
}